iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 4
1

今天要介紹的是 scope,這個東西是我還是新手時,常常搞不清楚的東西,說真的...即使現在有時候我也會回頭查一下該用哪個 scope,個人認為在使用 scope 時,已下五點觀念如果你都非常清楚,那麼就非常夠用了。

觀念一:
這兩個 scope 都是用來產生不同的命名域,就像是一間學校有兩個人都叫陳小明,如果要來區別我們只稱的陳小明是哪一位,可以用A班的陳小明和B班的陳小明來區別。

以下示範:

with tf.name_scope('name'):
    tf.placeholder(tf.int32, name='i1')

with tf.variable_scope('variable'):
    tf.placeholder(tf.int32, name='i2')

tensorboard 觀察結果:
https://ithelp.ithome.com.tw/upload/images/20190912/201072990cgNbwhkz7.png

這邊可以看到,在一般情況下,variable scope 和 name scope 所產生出來的結果並無差別,都是把變數包在某個 scope 底下。

觀念二:
既然上個例子沒有差別,那為什麼要有 variable scope? 這邊你必須要知道,在宣告 variable 時,其實有兩種方法。

tf.get_variable
tf.Variable

簡單解釋一下兩種差別,Variable()宣告的方式就跟一般寫程式一樣,直接new出一個物件出來,但是在tensorflow的世界裡,每個物件都必須有個專屬的節點名稱,如果你不斷宣告同個名稱的Variable,tensorflow會自動幫你在後面標記編號,例如:

tf.Variable(name="V", initial_value=0)
tf.Variable(name="V", initial_value=0)

在graph上就會有V_1、V_2。
而get_variable(),這方法則會幫你檢查名稱是否撞名,如果撞名就會直接噴錯,(除非符合 reuse 狀況,以下會提)。

tf.get_variable(name="V", shape=[1])
tf.get_variable(name="V", shape=[1])  # it will crash

但我個人認為,作為一個負責任(?) 的開發人員,你程式碼在變數命名時,就必須先規劃好,不要寫出會撞名的程式碼,因此我統一都使用 get_variable()來建立變數。

以下附上範例。

tf.get_variable(name="V", shape=[1])
tf.Variable(name="V", initial_value=0)
tf.Variable(name="V", initial_value=0)

tensorboard 觀察結果:
https://ithelp.ithome.com.tw/upload/images/20190912/20107299KNzbJ0LFpu.png

另外有個好玩的事情,如果你調換剛剛程式碼順序成

tf.Variable(name="V", initial_value=0)
tf.get_variable(name="V", shape=[1])
tf.Variable(name="V", initial_value=0)

你會發現get_variable()雖然撞名,但是撞的是Variable(),所以摸摸鼻子自己加了編號XD
https://ithelp.ithome.com.tw/upload/images/20190912/20107299ZSRHpZpDNr.png

因此我建議...,統一還是用get_variable()來實作你的網路。

觀念三:
get_variable()只在 variable scope 底下有反應,按照 tensorflow 的規則,如果你使用了get_variable(),又想將它放置在某個 scope 底下,那麼請使用 variable_scope。

with tf.name_scope('name'):
    tf.get_variable(name="V", shape=[1])

with tf.variable_scope('variable'):
    tf.get_variable(name="V", shape=[1])

tensorboard 觀察結果:
https://ithelp.ithome.com.tw/upload/images/20190912/20107299Rhv2tL81EK.png

觀念四:
所謂的 reuse 使用情境,當你在程式碼前面已宣告了某個 variable,在程式碼之後,會需要用到這個 variable 時,你可以使用 variable_scope 的 reuse 來重新取得,範例如下。

with tf.variable_scope("foo"):
    v = tf.get_variable("v", [1])

# 其他程式
# ...
# ...
# ...
# ...

with tf.variable_scope("foo", reuse=True):
    v1 = tf.get_variable("v", [1])
    
assert v1 == v

觀念五:
情境和四一樣,只是你也可以用 scope.reuse_variables(),來達到。

with tf.variable_scope("foo") as scope:
    v = tf.get_variable("v", [1])

    # 其他程式
    # ...
    # ...
    # ...
    # ...

    scope.reuse_variables()
    v1 = tf.get_variable("v", [1])

assert v1 == v

四和五的 graph 都如下圖,所拿到的 v 和 v1 都是同個tensor。
https://ithelp.ithome.com.tw/upload/images/20190912/20107299tmVAEePsAA.png

tensorflow 官方說明文件還有許多例子,這邊我只挑幾個出來,希望對大家有幫助,理解以上幾個觀念,可避免實作上採很多雷了。

Github原始碼

ref:
https://www.tensorflow.org/api_docs/python/tf/variable_scope

https://www.tensorflow.org/api_docs/python/tf/name_scope


上一篇
【03】新手常誤解的用法,tensorflow多個graph處理
下一篇
【05】tensorflow 的 convolution 方式好多種,我該用哪個...
系列文
How to Train Your Model 訓模高手:我的 Tensorflow 個人使用經驗系列文31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言